﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceProcess;
using System.Threading;
using System.Timers;

using Iit.ITBI.MDSManager;
using Enterprise.Statistics.WindowsServices.Common.Log;

namespace Iit.ITBI.MDSManagerService
{
    class MDSManagerService: ServiceBase
    {

        /// <summary>
        /// A timer object used to manage how often the Replicate() method is invoked.
        /// </summary>
        private System.Timers.Timer entityReplicatorTimer;
        /// <summary>
        /// A MasterEntityReplicator object used to replicate the master entities to the subscribing slave entities.
        /// </summary>
        private MasterEntityReplicator masterEntityReplicator;
        
        
        #region CTOR
        public MDSManagerService()
        {
            InitializeComponent();        
        }
        #endregion


        private void InitializeComponent()
        {
            this.ServiceName = "MDSManagerService";

            //Initialize the MasterEntityReplicator
            this.masterEntityReplicator = new MasterEntityReplicator();

            //hook event handlers to MasterEntityReplicator events
            this.masterEntityReplicator.OnInfo += masterEntityReplicator_OnInfo;
            this.masterEntityReplicator.OnWarning += masterEntityReplicator_OnWarning;
            this.masterEntityReplicator.OnError += masterEntityReplicator_OnError;

            NLogWriter.WriteLogger("Info", null, "On InitializeComponent");
        }

        /// <summary>
        /// The function is executed when a Start command is sent to the 
        /// service by SCM. It specifies actions to take when a service starts 
        /// running. 
        /// The action we take here are:
        /// Write an info log entry stating the start of the service
        /// Attach a new entityReplicatorTimer instance in a new thred, and start the thread.
        /// </summary>
        protected override void OnStart(string[] args)
        {

            //instantiate entityReplicatorTimer
            Thread t = new Thread(new ThreadStart(this.InitEntityReplicatorTimer));

            t.Start();

        }


        /// <summary>
        /// The function is executed when a Stop command is sent to the 
        /// service by SCM. It specifies actions to take when a service stops 
        /// running. 
        /// The action we take here are:
        /// Write an info log entry stating that the service is stopping
        /// disable the entityReplicatorTimer
        /// </summary>
        protected override void OnStop()
        {
            NLogWriter.WriteLogger("Info", null, "stop");

            entityReplicatorTimer.Enabled = false;
        }


        /// <summary>
        /// Initializes the entityReplicatorTimer object.
        /// </summary>
        private void InitEntityReplicatorTimer()
        {
            entityReplicatorTimer = new System.Timers.Timer();

            //wire up the entityReplicatorTimer event 
            entityReplicatorTimer.Elapsed += new ElapsedEventHandler(entityReplicatorTimer_Elapsed);

            //set the interval between timer elapsed events
            entityReplicatorTimer.Interval = Properties.Settings.Default.EntityReplicatorTimerInterval.TotalMilliseconds;
            
            //enable the timer
            entityReplicatorTimer.Enabled = true;
        }

        /// <summary>
        /// Handles the Elapsed event of the entityReplicatorTimer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="ElapsedEventArgs" /> instance containing the event data.</param>
        protected void entityReplicatorTimer_Elapsed(object sender, ElapsedEventArgs e)
        {

            try
            {
                //first we disable the timer, to make sure that we do not get consequent\ parallel invocation of the same timer.
                entityReplicatorTimer.Enabled = false;

                masterEntityReplicator.Replicate();
            }
            catch (Exception ex)
            {
                NLogWriter.WriteLogger("Error", null, ex.Message);

                throw;
            }
            finally
            {
                //regardless the result of the masterEntityReplicator.Replicate() we enable the timer
                entityReplicatorTimer.Enabled = true;
            }

        }

        #region Event Handlers
        public void masterEntityReplicator_OnInfo(object sender, MessageEventArgs e)
        {
            NLogWriter.WriteLogger("Info", null, e.Message, e);            
        }

        public void masterEntityReplicator_OnError(object sender, MessageEventArgs e)
        {
            NLogWriter.WriteLogger("Error", null, e.Message, e);            
        }

        public void masterEntityReplicator_OnWarning(object sender, MessageEventArgs e)
        {
            NLogWriter.WriteLogger("Warning", null, e.Message, e);            
        }
        #endregion

    }
}
